﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Controls = Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Shapes = Windows.UI.Xaml.Shapes;
using Windows.Devices.Input;
using Windows.Foundation;
using System.Windows;
using Configuration;
using Windows.UI.Text;
using Windows.UI.Xaml.Controls;
using BoolanElement.UI.Shapes.TextBoxShapes;
using BoolanSlide.ElementMenu;
using BoolanSlide.RedoUndo;
using BoolanSlide.UIElement.Shapes.TextShapes.Common;
using Windows.UI.Xaml.Media.Imaging;
using BoolanSlide.BooCommon;
using BoolanSlide.Language;

namespace BoolanElement
{
    public abstract class BooTextShapesBase : BooUIBase, IFocusEllOperation, IShapesStyleController, ITextStyleController
    {
        public abstract Shapes.Shape Shape
        {
            get;
        }

        public abstract BooTextShapesBaseElement TextShapesBaseElement
        {
            get;
        }

        public ShapesMenu ShapeMenu
        {
            set;
            get;
        }

        public override MenuBase UIMenu
        {
            get { return ShapeMenu; }
        }

        public RichEditBox TextBox { get; set; }
        public Controls.Grid FullGrid { get; set; }
        public Controls.StackPanel CenterStack { get; set; }
        public Shapes.Rectangle TextPol { get; set; }
        protected ControlPanel ShapesControlPanel;


        private int TextChangedAmount;
        private int CurrentTextAmount;


        private bool isLoaded = false;
        public bool isReSize = true;

        private bool IsRedoUndo;
        private bool IsThumb;

        public BooTextShapesBase(BooTextShapesBaseElement element)
        {
            IsRedoUndo = false;
            TextChangedAmount = 0;
            Window.Current.CoreWindow.PointerMoved += CoreWindow_PointerMoved;
            LanguageManager.LanguageChanged += LanguageManager_LanguageChanged;
            element.ShapePropertyChanged += element_ShapePropertyChanged;
        }

        void LanguageManager_LanguageChanged(object sender)
        {
            if (ShapesControlPanel != null)
            {
                ShapesControlPanel.ModifyTab(LanguageManager.StyleTabNormal2, LanguageManager.StyleTabDown2, LanguageManager.StyleTabDown2, 0);
                ShapesControlPanel.ModifyTab(LanguageManager.TextTabNormal2, LanguageManager.TextTabDown2, LanguageManager.TextTabDown2, 1);
            }
        }

        public void InitOriginal()
        {
            IsThumb = false;
            CreateShape();
            InitShapesStyle();
            InitEvents();

            Focus.InsertFocusEllipses(BooCanvas);
            Focus.SetFocuseEllipseMargin(Element.ElementTransform.Width, Element.ElementTransform.Height);

            InitializeActionMap(BooCanvas);
            InitContextMenu();
            InitShapesControlPanel();

            LostFocus();

            this.TextBox.IsReadOnly = false;
        }

        public void InitOriginalForThumbNails()
        {
            IsThumb = true;
            CreateShape();
            InitShapesStyle();
            TextBox.Loaded += TextBox_Loaded;
            this.TextBox.IsEnabled = false;
            ApplyTransform(BooCanvas);
            BooCanvas.ManipulationMode = ManipulationModes.All;
            LostFocus();

            this.TextBox.IsReadOnly = false;
        }

        void element_ShapePropertyChanged(object sender, ShapePropertyChangedArgs args)
        {
            ApplyChange(args);
        }

        public virtual void ApplyChange(ShapePropertyChangedArgs args)
        {
            if (args.PropertyName == "Style")
            {
                ApplyStyle();
            }
            else if (args.PropertyName == "Shape")
            {
                ApplySize();
            }
            else if (args.PropertyName == "Text")
            {
                ApplyText(args.ShouldSaveForRedoUndo);
            }
            else if (args.PropertyName == "UpdateUI")
            {
                ApplyUpdateUI(args.Data as BooElement);
            }
        }

        public virtual void ApplyStyle()
        {
            Shape.Stroke = new SolidColorBrush(TextShapesBaseElement.BorderColor);
            Shape.Fill = new SolidColorBrush(TextShapesBaseElement.ShapeFillColor);



            if (!IsThumb && Shape.StrokeThickness - TextShapesBaseElement.BorderWidth == 0)
                RedoUndoHelper.SaveStatus(this);
            Shape.StrokeThickness = TextShapesBaseElement.BorderWidth;
        }

        public virtual void ApplySize()
        {

        }

        public virtual void ApplyText(bool shouldSaveForRedoUndo)
        {
            string text;
            TextBox.Document.GetText(TextGetOptions.FormatRtf | TextGetOptions.AdjustCrlf, out text);
            if (text == TextShapesBaseElement.Text)
            {
                if (!IsThumb && shouldSaveForRedoUndo)
                    RedoUndoHelper.SaveStatus(this);
                return;
            }



            TextBox.IsReadOnly = false;
            TextBox.Document.SetText(TextSetOptions.ApplyRtfDocumentDefaults | TextSetOptions.FormatRtf, TextShapesBaseElement.Text);
            TextBox.IsReadOnly = true;
            ApplyFontAlignment(TextShapesBaseElement.TextAlignment);



        }

        public virtual void ApplyUpdateUI(BooElement element)
        {
            LoadFromElement(element);
            TextBox.IsReadOnly = false;
            TextBox.Document.SetText(TextSetOptions.FormatRtf | TextSetOptions.ApplyRtfDocumentDefaults, TextShapesBaseElement.Text);
            TextBox.Document.GetRange(0, TextConstants.MaxUnitCount).CharacterFormat.BackgroundColor = Colors.Transparent;
            TextBox.IsReadOnly = true;
            Shape.Stroke = new SolidColorBrush(TextShapesBaseElement.BorderColor);
            Shape.StrokeThickness = TextShapesBaseElement.BorderWidth;
            Shape.Fill = new SolidColorBrush(TextShapesBaseElement.ShapeFillColor);
            ApplyFontAlignment(TextShapesBaseElement.TextAlignment);
        }

        void BooCanvas_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            if (System.DateTime.Now.Ticks - PressedTicks < GlobalVariable.ShowMenuTime && Manipulationed == false)
                this.ShapeMenu.ShowMenu();
        }

        void BooCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            PressedTicks = System.DateTime.Now.Ticks;
            Manipulationed = false;
        }

        public void CreateShape()
        {
            InitShape();

            //最外层BooCanvas
            //BooCanvas.DoubleTapped += Canvas_DoubleTapped;                     
            //第三层FullGrid
            FullGrid = new Controls.Grid();
            //第四层CenterStackPanel
            CenterStack = new Controls.StackPanel();
            //A TextBox in the CenterStackPanel
            TextBox = new RichEditBox();
            //TextBox.Loaded += TextBox_Loaded;    
            //the fifth layout
            TextPol = new Shapes.Rectangle();

            BooCanvas.Children.Add(Shape);
            BooCanvas.Children.Add(FullGrid);
            FullGrid.Children.Add(CenterStack);
            CenterStack.Children.Add(TextBox);
            FullGrid.Children.Add(TextPol);
        }

        public virtual void InitShapesStyle()
        {
            Shape.Stroke = new SolidColorBrush(TextShapesBaseElement.BorderColor);
            Shape.StrokeThickness = TextShapesBaseElement.BorderWidth;
            Shape.Fill = new SolidColorBrush(TextShapesBaseElement.ShapeFillColor);

            FullGrid.Width = TextShapesBaseElement.ShapeWidth;
            FullGrid.Height = TextShapesBaseElement.ShapeHeight;

            CenterStack.Width = TextShapesBaseElement.TextWidth;
            CenterStack.Margin = new Thickness(TextShapesBaseElement.TextMarginLeft, TextShapesBaseElement.TextMarginTop, 0, 0);
            CenterStack.Background = new SolidColorBrush(Colors.Transparent);
            CenterStack.VerticalAlignment = VerticalAlignment.Center;

            TextBox.Width = TextShapesBaseElement.TextWidth;
            TextBox.Background = new SolidColorBrush(Colors.Transparent);
            TextBox.TextWrapping = TextWrapping.Wrap;
            TextBox.AcceptsReturn = true;
            TextBox.BorderThickness = new Thickness(0, 0, 0, 0);
            TextBox.ManipulationMode = ManipulationModes.All;
            //this.TextBox.Background = new SolidColorBrush(Colors.CadetBlue);
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;

            TextPol.Fill = new SolidColorBrush(Colors.Transparent);
        }

        public abstract void InitShape();

        public void InitEvents()
        {
            BooCanvas.DoubleTapped += Canvas_DoubleTapped;
            BooCanvas.PointerPressed += BooCanvas_PointerPressed;
            BooCanvas.PointerReleased += BooCanvas_PointerReleased;

            TextBox.Loaded += TextBox_Loaded;
            TextBox.KeyUp += TextBox_KeyUp;
            TextBox.LostFocus += TextBox_LostFocus;
            TextBox.GotFocus += TextBox_GotFocus;

            TextBox.SelectionChanged += TextBox_SelectionChanged;
            TextBox.ManipulationStarted += TextBox_ManipulationStarted;
            TextBox.ManipulationCompleted += TextBox_ManipulationCompleted;


        }



        public override void GotFocus()
        {
            base.GotFocus();
            ShowShapesControlPanel(this);
            //this.TextBox.Document.Selection.EndPosition = this.TextShapesBaseElement.Text.Length;

            this.TextBox.IsReadOnly = false;
        }

        public override void LostFocus()
        {
            if (this.TextBox.IsReadOnly == true)
                return;

            base.LostFocus();

            TextBox_LostFocus(null, null);

            ITextRange textRange = this.TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            if (textRange.Text != String.Empty && textRange.Text != "\r")
            {
                textRange.CharacterFormat.BackgroundColor = Colors.Transparent;

                this.TextBox.Document.GetText(TextGetOptions.FormatRtf | TextGetOptions.AdjustCrlf, out this.TextShapesBaseElement._Text);
            }

            HideShapesControlPanel();
            if (ShapeMenu != null)
                ShapeMenu.HideMenu();

            this.TextBox.IsReadOnly = true;
            //this.TextBox.Document.Selection.EndPosition = 0;
        }

        /// <summary>
        /// 用于RedoUndo时更新控件信息
        /// </summary>
        /// <param name="booElement"></param>
        public override void UpdateUI(BooElement booElement)
        {
            IsRedoUndo = true;
            (Element as BooTextShapesBaseElement).UpdateUI(booElement.Clone());
        }

        public virtual void LoadFromElement(BooElement booElement)
        {
            ReSizeUI(booElement.ElementTransform.Width - Element.ElementTransform.Width, booElement.ElementTransform.Height - Element.ElementTransform.Height);
            (Element as BooTextShapesBaseElement).Load(booElement as BooTextShapesBaseElement);
            base.ApplyTransform(BooCanvas);
        }

        protected override void BooUIBase_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            base.BooUIBase_ManipulationCompleted(sender, e);
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public void InitContextMenu()
        {
            ShapeMenu = new ShapesMenu(this);
        }

        #region ControlPanel
        public void InitShapesControlPanel()
        {
            ShapesControlPanel = new ControlPanel();
            ShapeStyle pageStyle = new ShapeStyle();

            ShapeText pageText = new ShapeText();

            ShapesControlPanel.AddTab(LanguageManager.StyleTabNormal2, LanguageManager.StyleTabDown2, LanguageManager.StyleTabDown2, pageStyle);
            ShapesControlPanel.AddTab(LanguageManager.TextTabNormal2, LanguageManager.TextTabDown2, LanguageManager.TextTabDown2, pageText);

        }

        public void ShowShapesControlPanel(IStyleController styleController)
        {
            if (ShapesControlPanel != null)
            {
                ShapesControlPanel.ShowControlPanel(styleController);
            }
        }

        public void HideShapesControlPanel()
        {
            if (ShapesControlPanel != null)
            {
                ShapesControlPanel.HideControlPanel();
            }
        }
        #endregion

        #region events

        private void TextBox_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            e.Handled = true;
        }

        private void TextBox_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            e.Handled = true;
        }

        void TextBox_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Enter)
                RedoUndoHelper.SaveStatus(this);
        }

        protected void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            TextBox.TextChanged += TextBox_TextChanged;
            if (TextBox.IsReadOnly == true)
                return;

            HandledAcceleratorBySelf = true;

            ITextRange textRange = this.TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            textRange.CharacterFormat.BackgroundColor = Colors.Transparent;
        }

        protected void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            TextBox.TextChanged -= TextBox_TextChanged;
            if (this.TextBox.IsReadOnly == true)
                return;

            if (sender == null && e == null)
                HandledAcceleratorBySelf = false;

            if (TextBox.Document.Selection.Text != "" && TextBox.Document.Selection.Text != "\r")
            {
                ITextSelection textSelection = TextBox.Document.Selection;
                textSelection.CharacterFormat.BackgroundColor = Configuration.ConstColor.TextSelectionColor;
                //textSelection.CharacterFormat.BackgroundColor = Colors.Transparent;
            }

            this.TextPol.Visibility = Visibility.Visible;
            if (TextBox.FocusState == FocusState.Unfocused)
                return;

            this.TextBox.Document.Selection.StartPosition = TextConstants.MaxUnitCount;
            this.TextBox.Document.Selection.EndPosition = TextConstants.MaxUnitCount;
            this.TextBox.Document.Selection.StartPosition++;

            RedoUndoHelper.SaveStatus(this);
        }

        protected void TextBox_TextChanged(object sender, RoutedEventArgs e)
        {
            if (IsRedoUndo)
            {
                IsRedoUndo = false;
                return;
            }
            if (isLoaded == true)
            {
                this.TextBox.Document.GetText(TextGetOptions.FormatRtf | TextGetOptions.AdjustCrlf, out this.TextShapesBaseElement._Text);
                RichTextChanged(false);
            }
            string text;
            TextBox.Document.GetText(TextGetOptions.None, out text);
            int amount = text.Length - CurrentTextAmount;
            if (TextChangedAmount * amount >= 0)
            {
                TextChangedAmount += amount;
            }
            else
            {
                TextChangedAmount = 0;
            }
            CurrentTextAmount = text.Length;
            if (Math.Abs(TextChangedAmount) > Configuration.GlobalVariable.DeleteTextLengthCanSave || Math.Abs(amount) > 1)
            {
                TextChangedAmount = 0;
                RedoUndoHelper.SaveStatus(this);
            }
            IsRedoUndo = false;
        }

        protected void TextBox_Loaded(object sender, RoutedEventArgs e)
        {
            if (isLoaded == true)
                return;
            isLoaded = true;
            TextBox.IsReadOnly = false;
            TextBox.Document.SetText(TextSetOptions.FormatRtf | TextSetOptions.ApplyRtfDocumentDefaults, this.TextShapesBaseElement.Text);
            CurrentTextAmount = this.TextShapesBaseElement.Text.Length;
            TextBox.IsReadOnly = true;
            if (this.TextShapesBaseElement.Text == "" || this.TextShapesBaseElement.Text == "\r")
            {
                ITextCharacterFormat defaultFormat = this.TextBox.Document.GetDefaultCharacterFormat();
                defaultFormat.Size = 14;
                defaultFormat.Name = "Microsoft YaHei UI";
                this.TextBox.Document.SetDefaultCharacterFormat(defaultFormat);
            }
        }

        protected void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
        {
            if (TextBox.FocusState == FocusState.Unfocused)
                return;
            if (this.TextPol.Visibility == Visibility.Visible)
                return;

            ShowShapesControlPanel(this);
            ITextRange textRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            textRange.CharacterFormat.BackgroundColor = Colors.Transparent;
        }
        #endregion

        /// <summary>
        /// 双击画布,进入TextBox编辑状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Canvas_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
        {
            TextBox.Focus(FocusState.Keyboard);

            ShapeMenu.ShowMenu();

            TextPol.Visibility = Visibility.Collapsed;
            TextBox.Document.Selection.StartPosition = TextConstants.MaxUnitCount;
        }

        protected override void BooUIBase_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            base.BooUIBase_ManipulationDelta(sender, e);
            ShapeMenu.HideMenu();
        }

        public abstract void ReSizeUI(double x, double y);

        public abstract void ReMargin(double x, double y);

        #region FocusOperation
        public virtual void left_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            //求对角线的单位向量
            Thickness margin1 = Focus.FocusElls.left_top_ell.Margin;
            Thickness margin2 = Focus.FocusElls.right_bottom_ell.Margin;
            Point cornerUnitVector = new Point(margin1.Left - margin2.Left, margin1.Top - margin2.Top);
            double length = Math.Sqrt(cornerUnitVector.X * cornerUnitVector.X + cornerUnitVector.Y * cornerUnitVector.Y);
            cornerUnitVector.X /= length;
            cornerUnitVector.Y /= length;
            //旋转单位向量
            Point orig = cornerUnitVector;
            cornerUnitVector.X = orig.X * Math.Cos(angle) - orig.Y * Math.Sin(angle);
            cornerUnitVector.Y = orig.X * Math.Sin(angle) + orig.Y * Math.Cos(angle);
            //求小圆点的移动向量
            double deltaX = e.Delta.Translation.X;
            //double deltaY = e.Delta.Translation.X * (this.Element.ElementTransform.Height / this.Element.ElementTransform.Width);
            double deltaY = e.Delta.Translation.Y;
            Point moveVector = new Point(deltaX, deltaY);

            double distance = moveVector.X * cornerUnitVector.X + moveVector.Y * cornerUnitVector.Y;

            double tanAngle = this.Element.ElementTransform.Width / this.Element.ElementTransform.Height;
            double angle2 = Math.Atan(tanAngle);


            double width = Math.Sin(angle2) * distance;
            double height = Math.Cos(angle2) * distance;
            if (this.TextShapesBaseElement.ElementTransform.Width + width < 50 || this.TextShapesBaseElement.ElementTransform.Height + height < 50)
            {
                return;
            }
            ReSizeUI(width, height);

            double marginX = -height * Math.Sin(angle) + width * Math.Cos(angle);
            double marginY = -height * Math.Cos(angle) - width * Math.Sin(angle);



            ReMargin(-marginX, marginY);
        }

        public virtual void middle_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double deltaX = e.Delta.Translation.X;
            double deltaY = e.Delta.Translation.Y;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            double height = Math.Sin(angle) * deltaX - Math.Cos(angle) * deltaY;

            if (this.TextShapesBaseElement.ElementTransform.Height + height < 50)
            {
                return;
            }
            ReSizeUI(0, height);
            ReMargin(height * Math.Sin(angle), -height * Math.Cos(angle));

        }

        public virtual void right_top_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            //求对角线的单位向量
            Thickness margin1 = Focus.FocusElls.right_top_ell.Margin;
            Thickness margin2 = Focus.FocusElls.left_bottom_ell.Margin;
            Point cornerUnitVector = new Point(margin1.Left - margin2.Left, margin1.Top - margin2.Top);
            double length = Math.Sqrt(cornerUnitVector.X * cornerUnitVector.X + cornerUnitVector.Y * cornerUnitVector.Y);
            cornerUnitVector.X /= length;
            cornerUnitVector.Y /= length;
            //旋转单位向量
            Point orig = cornerUnitVector;
            cornerUnitVector.X = orig.X * Math.Cos(angle) - orig.Y * Math.Sin(angle);
            cornerUnitVector.Y = orig.X * Math.Sin(angle) + orig.Y * Math.Cos(angle);
            //求小圆点的移动向量
            double deltaX = e.Delta.Translation.X;
            //double deltaY = e.Delta.Translation.X * (this.Element.ElementTransform.Height / this.Element.ElementTransform.Width);
            double deltaY = e.Delta.Translation.Y;
            Point moveVector = new Point(deltaX, deltaY);

            double distance = moveVector.X * cornerUnitVector.X + moveVector.Y * cornerUnitVector.Y;

            double tanAngle = this.Element.ElementTransform.Width / this.Element.ElementTransform.Height;
            double angle2 = Math.Atan(tanAngle);


            double width = Math.Sin(angle2) * distance;
            double height = Math.Cos(angle2) * distance;

            if (this.TextShapesBaseElement.ElementTransform.Width + width < 50 || this.TextShapesBaseElement.ElementTransform.Height + height < 50)
            {
                return;
            }

            ReSizeUI(width, height);

            double marginX = height * Math.Sin(angle);
            double marginY = -height * Math.Cos(angle);
            ReMargin(marginX, marginY);

        }

        public virtual void right_middle_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double deltaX = e.Delta.Translation.X;
            double deltaY = e.Delta.Translation.Y;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            double width = Math.Cos(angle) * deltaX + Math.Sin(angle) * deltaY;

            ReSizeUI(width, 0);
        }

        public virtual void right_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            //求对角线的单位向量
            Thickness margin1 = Focus.FocusElls.right_bottom_ell.Margin;
            Thickness margin2 = Focus.FocusElls.left_top_ell.Margin;
            Point cornerUnitVector = new Point(margin1.Left - margin2.Left, margin1.Top - margin2.Top);
            double length = Math.Sqrt(cornerUnitVector.X * cornerUnitVector.X + cornerUnitVector.Y * cornerUnitVector.Y);
            cornerUnitVector.X /= length;
            cornerUnitVector.Y /= length;
            //旋转单位向量
            Point orig = cornerUnitVector;
            cornerUnitVector.X = orig.X * Math.Cos(angle) - orig.Y * Math.Sin(angle);
            cornerUnitVector.Y = orig.X * Math.Sin(angle) + orig.Y * Math.Cos(angle);
            //求小圆点的移动向量
            double deltaX = e.Delta.Translation.X;
            //double deltaY = e.Delta.Translation.X * (this.Element.ElementTransform.Height / this.Element.ElementTransform.Width);
            double deltaY = e.Delta.Translation.Y;
            Point moveVector = new Point(deltaX, deltaY);

            double distance = moveVector.X * cornerUnitVector.X + moveVector.Y * cornerUnitVector.Y;

            double tanAngle = this.Element.ElementTransform.Width / this.Element.ElementTransform.Height;
            double angle2 = Math.Atan(tanAngle);


            double width = Math.Sin(angle2) * distance;
            double height = Math.Cos(angle2) * distance;

            ReSizeUI(width, height);

        }

        public virtual void middle_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double deltaX = e.Delta.Translation.X;
            double deltaY = e.Delta.Translation.Y;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            double height = Math.Sin(angle) * deltaX - Math.Cos(angle) * deltaY;
            ReSizeUI(0, -height);
        }

        public virtual void left_bottom_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            //求对角线的单位向量
            Thickness margin1 = Focus.FocusElls.left_bottom_ell.Margin;
            Thickness margin2 = Focus.FocusElls.right_top_ell.Margin;
            Point cornerUnitVector = new Point(margin1.Left - margin2.Left, margin1.Top - margin2.Top);
            double length = Math.Sqrt(cornerUnitVector.X * cornerUnitVector.X + cornerUnitVector.Y * cornerUnitVector.Y);
            cornerUnitVector.X /= length;
            cornerUnitVector.Y /= length;
            //旋转单位向量
            Point orig = cornerUnitVector;
            cornerUnitVector.X = orig.X * Math.Cos(angle) - orig.Y * Math.Sin(angle);
            cornerUnitVector.Y = orig.X * Math.Sin(angle) + orig.Y * Math.Cos(angle);
            //求小圆点的移动向量
            double deltaX = e.Delta.Translation.X;
            //double deltaY = e.Delta.Translation.X * (this.Element.ElementTransform.Height / this.Element.ElementTransform.Width);
            double deltaY = e.Delta.Translation.Y;
            Point moveVector = new Point(deltaX, deltaY);

            double distance = moveVector.X * cornerUnitVector.X + moveVector.Y * cornerUnitVector.Y;

            double tanAngle = this.Element.ElementTransform.Width / this.Element.ElementTransform.Height;
            double angle2 = Math.Atan(tanAngle);


            double width = Math.Sin(angle2) * distance;
            double height = Math.Cos(angle2) * distance;

            double marginX = -width * Math.Cos(angle);
            double marginY = -width * Math.Sin(angle);
            if (this.TextShapesBaseElement.ElementTransform.Width + width < 50 || this.TextShapesBaseElement.ElementTransform.Height + height < 50)
            {
                return;
            }
            ReSizeUI(width, height);
            ReMargin(marginX, marginY);
        }

        public virtual void left_middle_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            e.Handled = true;
            double deltaX = e.Delta.Translation.X;
            double deltaY = e.Delta.Translation.Y;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            double width = Math.Cos(angle) * deltaX + Math.Sin(angle) * deltaY;
            if (this.TextShapesBaseElement.ElementTransform.Width + width < 50)
            {
                return;
            }
            ReSizeUI(-width, 0);
            ReMargin(width * Math.Cos(angle), width * Math.Sin(angle));
        }

        public virtual void left_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void middle_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void right_top_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void right_middle_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void right_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void middle_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void left_bottom_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public virtual void left_middle_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }
        #endregion

        #region ChangeStyle
        public void ChangeFontSizeTo(double size, bool shouldSaveForRedoUndo = false)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);

            textRange.CharacterFormat.Size = (float)size;
            RichTextChanged(shouldSaveForRedoUndo);
        }

        public double GetFontSize()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.Size;
        }

        public void ChangeFontBoldStatusTo(FormatEffect status)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);
            textRange.CharacterFormat.Bold = status;
            RichTextChanged();
        }

        public FormatEffect GetFontBoldStatus()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.Bold;
        }

        public void ChangeFontItalicStatusTo(FormatEffect status)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);
            textRange.CharacterFormat.Italic = status;
            RichTextChanged();
        }

        public FormatEffect GetFontItalicStatus()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.Italic;
        }

        public void ChangeFontUnderLineStatusTo(UnderlineType status)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);
            textRange.CharacterFormat.Underline = status;
            RichTextChanged();
        }

        public UnderlineType GetFontUnderLineStatus()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.Underline;
        }

        public void ChangeFontStrikethroughStatusTo(FormatEffect status)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);
            textRange.CharacterFormat.Strikethrough = status;
            RichTextChanged();
        }

        public FormatEffect GetFontStrikethroughStatus()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.Strikethrough;
        }

        public void ChangeFontColorTo(Color color)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);
            textRange.CharacterFormat.ForegroundColor = color;
            RichTextChanged();
        }

        public Color GetFontColor()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.ForegroundColor;
        }

        public void ChangeFontFamilyTo(string family)
        {
            ITextRange textRange = GetRangeForSetStyle(this.TextBox);
            textRange.CharacterFormat.Name = family;
            RichTextChanged();
        }

        public string GetFontFamily()
        {
            ITextRange textRange = GetRangeForGetStyle(this.TextBox);
            return textRange.CharacterFormat.Name;
        }

        public void ChangeFontAlignmentTo(Configuration.TextAlignment alignment)
        {
            switch (alignment)
            {
                case Configuration.TextAlignment.LeftTop: ChangeTextLeftTop(); break;
                case Configuration.TextAlignment.CenterTop: ChangeCenterTop(); break;
                case Configuration.TextAlignment.RightTop: ChangeRightTop(); break;
                case Configuration.TextAlignment.LeftCenter: ChangeLeftCenter(); break;
                case Configuration.TextAlignment.CenterCenter: ChangeCenterCenter(); break;
                case Configuration.TextAlignment.RightCenter: ChangeRightCenter(); break;
                case Configuration.TextAlignment.LeftBottom: ChangeLeftBottom(); break;
                case Configuration.TextAlignment.CenterBottom: ChangeCenterBottom(); break;
                case Configuration.TextAlignment.RightBottom: ChangeRightBottom(); break;
                default: throw new Exception();
            }
            //RichTextChanged();
        }

        public void ApplyFontAlignment(Configuration.TextAlignment alignment)
        {
            TextBox.IsReadOnly = false;
            TextBox.Document.Selection.StartPosition = 0;
            TextBox.Document.Selection.EndPosition = TextConstants.MaxUnitCount;
            ITextSelection searchRange = TextBox.Document.Selection;
            switch (alignment)
            {
                case Configuration.TextAlignment.LeftTop:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Left;
                    CenterStack.VerticalAlignment = VerticalAlignment.Top;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Left;
                    break;
                case Configuration.TextAlignment.CenterTop:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Center;
                    CenterStack.VerticalAlignment = VerticalAlignment.Top;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;
                    break;
                case Configuration.TextAlignment.RightTop:
       
                    CenterStack.VerticalAlignment = VerticalAlignment.Top;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Right;
                    break;
                case Configuration.TextAlignment.LeftCenter:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Left;
                    CenterStack.VerticalAlignment = VerticalAlignment.Center;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Left;
                    break;
                case Configuration.TextAlignment.CenterCenter:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Center;
                    CenterStack.VerticalAlignment = VerticalAlignment.Center;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;
                    break;
                case Configuration.TextAlignment.RightCenter:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Right;
                    CenterStack.VerticalAlignment = VerticalAlignment.Center;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Right;
                    break;
                case Configuration.TextAlignment.LeftBottom:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Left;
                    CenterStack.VerticalAlignment = VerticalAlignment.Bottom;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Left;
                    break;
                case Configuration.TextAlignment.CenterBottom:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Center;
                    CenterStack.VerticalAlignment = VerticalAlignment.Bottom;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;
                    break;
                case Configuration.TextAlignment.RightBottom:
                    CenterStack.HorizontalAlignment = HorizontalAlignment.Right;
                    CenterStack.VerticalAlignment = VerticalAlignment.Bottom;
                    searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Right;
                    break;
                default: throw new Exception();
            }
            TextBox.Document.Selection.StartPosition = 0;
            TextBox.Document.Selection.EndPosition = 0;
            TextBox.IsReadOnly = true;
        }

        public Configuration.TextAlignment GetFontAlignment()
        {
            return TextShapesBaseElement.TextAlignment;
        }

        public virtual void ChangeShapeStyleTo(Configuration.ShapeStyle style)
        {
            if (style == Configuration.ShapeStyle.NoBorderNoBKG)
            {
                Shape.Fill = new SolidColorBrush(Colors.Transparent);
                Shape.StrokeThickness = 0;
                Shape.Stroke = new SolidColorBrush(Colors.Transparent);
            }
            else if (style == Configuration.ShapeStyle.BorderNoBKG)
            {
                Shape.Fill = new SolidColorBrush(Colors.Transparent);
                Shape.Stroke = new SolidColorBrush(Color.FromArgb(255, 24, 122, 169));
                Shape.StrokeThickness = 1;
            }
            else if (style == Configuration.ShapeStyle.NoBorderBKG)
            {
                Shape.StrokeThickness = 0;
                Shape.Fill = new SolidColorBrush(Color.FromArgb(255, 24, 122, 169));
            }
            else if (style == Configuration.ShapeStyle.BorderBKG)
            {
                Shape.StrokeThickness = 1;
                Shape.Stroke = new SolidColorBrush(Color.FromArgb(255, 24, 122, 169));
                Shape.Fill = new SolidColorBrush(Color.FromArgb(255, 146, 208, 81));
            }

            TextShapesBaseElement.ShapeFillColor = ((SolidColorBrush)Shape.Fill).Color;
            TextShapesBaseElement.BorderWidth = Shape.StrokeThickness;
            TextShapesBaseElement.BorderColor = ((SolidColorBrush)Shape.Stroke).Color;

            TextShapesBaseElement.ShapeStyle = style;

            TextShapesBaseElement.PropertyChanged("Style");
        }

        public Configuration.ShapeStyle GetShapeStyle()
        {
            return TextShapesBaseElement.ShapeStyle;
        }

        public virtual void ChangeShapeFillColorTo(Color color)
        {
            TextShapesBaseElement.ShapeFillColor = color;
            TextShapesBaseElement.PropertyChanged("Style");
        }

        public Color GetShapeFillColor()
        {
            return ((SolidColorBrush)Shape.Fill).Color;
        }

        public virtual void ChangeBorderColorTo(Color color)
        {
            TextShapesBaseElement.BorderColor = color;
            TextShapesBaseElement.PropertyChanged("Style");
        }

        public Color GetBorderColor()
        {
            return ((SolidColorBrush)Shape.Stroke).Color;
        }

        public virtual void ChangeBorderWidthTo(double width)
        {
            TextShapesBaseElement.BorderWidth = width;
            TextShapesBaseElement.PropertyChanged("Style");
        }

        public double GetBorderWidth()
        {
            return Shape.StrokeThickness;
        }


        public void ChangeBorderWidthCompleted()
        {
            RedoUndoHelper.SaveStatus(this);
        }

        #region 修改文本对齐方式
        public void ChangeTextLeftTop()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Left;
            CenterStack.VerticalAlignment = VerticalAlignment.Top;
            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.LeftTop;

            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeCenterTop()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Center;
            CenterStack.VerticalAlignment = VerticalAlignment.Top;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.CenterTop;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeRightTop()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Right;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Right;
            CenterStack.VerticalAlignment = VerticalAlignment.Top;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.RightTop;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeLeftCenter()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Left;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Left;
            CenterStack.VerticalAlignment = VerticalAlignment.Center;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.LeftCenter;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeCenterCenter()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Center;
            CenterStack.VerticalAlignment = VerticalAlignment.Center;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.CenterCenter;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeRightCenter()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Right;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Right;
            CenterStack.VerticalAlignment = VerticalAlignment.Center;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.RightCenter;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeLeftBottom()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Left;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Left;
            CenterStack.VerticalAlignment = VerticalAlignment.Bottom;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.LeftBottom;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeCenterBottom()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Center;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Center;
            CenterStack.VerticalAlignment = VerticalAlignment.Bottom;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.CenterBottom;
            RedoUndoHelper.SaveStatus(this);
        }

        public void ChangeRightBottom()
        {
            ITextRange searchRange = TextBox.Document.GetRange(0, TextConstants.MaxUnitCount);
            searchRange.ParagraphFormat.Alignment = ParagraphAlignment.Right;

            CenterStack.HorizontalAlignment = HorizontalAlignment.Right;
            CenterStack.VerticalAlignment = VerticalAlignment.Bottom;

            TextShapesBaseElement.TextAlignment = Configuration.TextAlignment.RightBottom;
            RedoUndoHelper.SaveStatus(this);
        }

        public void RichTextChanged(bool shouldSaveForRedoUndo = true)
        {
            string res;
            TextBox.Document.GetText(TextGetOptions.FormatRtf | TextGetOptions.AdjustCrlf, out res);
            TextShapesBaseElement.Text = res;
            ShapePropertyChangedArgs args = new ShapePropertyChangedArgs();
            args.PropertyName = "Text";
            args.ShouldSaveForRedoUndo = shouldSaveForRedoUndo;
            TextShapesBaseElement.PropertyChanged(args);

        }

        #endregion 修改文本对齐方式
        #endregion


        private ITextRange GetRangeForGetStyle(RichEditBox textBox)
        {
            ITextRange textRange;

            textRange = textBox.Document.GetRange(textBox.Document.Selection.StartPosition, textBox.Document.Selection.StartPosition + 1);

            if (textRange.Text == "" || textRange.Text == "\r")
                textRange = textBox.Document.GetRange(0, 1);

            return textRange;
        }

        private ITextRange GetRangeForSetStyle(RichEditBox textBox)
        {
            ITextRange textRange;

            textRange = textBox.Document.GetRange(textBox.Document.Selection.StartPosition, textBox.Document.Selection.EndPosition);

            if (textRange.Text == "" || textRange.Text == "\r")
                textRange = textBox.Document.GetRange(0, TextConstants.MaxUnitCount);

            return textRange;
        }


        public void ChangeZIndexTo(int index)
        {
            this.TextShapesBaseElement.ElementTransform.ZIndex = index;
        }

        public int GetZIndex()
        {
            return this.TextShapesBaseElement.ElementTransform.ZIndex;
        }


        public void ChangeListStyleTo(BoolanSlide.UIElement.TextBox.TextListStyleArgs TextListStyle)
        {

        }

        public void rotate_ell_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {

        }

        void CoreWindow_PointerMoved(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.PointerEventArgs args)
        {
            if (IsRotate)
            {
                Point mousePoint = args.CurrentPoint.Position;
                mousePoint.X -= TextShapesBaseElement.ElementTransform.Translate.X + TextShapesBaseElement.ShapeWidth / 2 + UIMargin.MainCanvasRect.Left;
                mousePoint.Y -= TextShapesBaseElement.ElementTransform.Translate.Y + TextShapesBaseElement.ShapeHeight / 2 + UIMargin.MainCanvasRect.Top;
                Point orig = new Point(0, -50);
                double angle = BooMath.GetAngleFromThreePoints(new Point(0, 0), orig, mousePoint);
                Element.ElementTransform.Rotate.CenterX = TextShapesBaseElement.ShapeWidth / 2;
                Element.ElementTransform.Rotate.CenterY = TextShapesBaseElement.ShapeHeight / 2;
                Element.ElementTransform.Rotate.Angle = angle;
            }
        }

        public void rotate_ell_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            IsRotate = false;
            RedoUndoHelper.SaveStatus(this);
            e.Handled = true;
        }

        public void rotate_ell_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            IsRotate = true;
            e.Handled = true;
        }

        public override BooElement Element
        {
            get
            {
                return this.TextShapesBaseElement;
            }
        }

        public override bool CanHandledAcceleratorBySelf()
        {
            return HandledAcceleratorBySelf;
        }
    }
}
